﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Xml.Linq;

namespace ApocDev.TownsApi.XmlFiles
{
    public class PrioritiesXml : ObservableCollection<Priority>
    {
        // Unfortunately, this is one of those files where things have to be "specially" handled to allow
        // people to create their own things.
        public PrioritiesXml(string actionsPath)
        {
            ModFiles.Priorities = this;
            XElement root = XElement.Load(actionsPath);
            IEnumerable<XElement> elements = root.Elements();
            int total = elements.Count();
            ModFiles.FireLoadEvent(this, new FileLoadEventArgs("Zones", total, 0));
            int numLoaded = 0;
            foreach (XElement xml in elements)
            {
                Add(new Priority(xml));
                ModFiles.FireLoadEvent(this, new FileLoadEventArgs("Zones", total, ++numLoaded));
            }
        }

        public bool IsDirty { get { return this.Any(a => a.IsDirty); } }

        public XElement SaveDirty()
        {
            if (!IsDirty)
                return null;
            var actions = new XElement("zones");
            foreach (Priority a in this)
            {
                if (a.IsDirty)
                    actions.Add(a.Save());
            }
            return actions;
        }

        public XElement Save()
        {
            var actions = new XElement("zones");
            foreach (Priority a in this)
            {
                actions.Add(a.Save());
            }
            return actions;
        }
    }

    public class Priority : IEquatable<Priority>, IChangedXml
    {
        private readonly int _originalHash;

        public Priority(XElement xml)
        {
            foreach (XElement e in xml.Elements())
            {
                switch (e.Name.LocalName.ToLower())
                {
                    case "id":
                        ID = e.Value;
                        break;
                    case "name":
                        Name = e.Value;
                        break;
                    case "icon":
                        Icon = e.Value;
                        break;
                    default:
                        MessageBox.Show("Unknown element for " + GetType().Name + ": " + e.Name.LocalName);
                        break;
                }
            }
            _originalHash = GetHashCode();
        }

        public string ID { get; set; }
        public string Name { get; set; }
        public string Icon { get; set; }
        public bool IsDirty { get { return _originalHash != GetHashCode(); } }

        public XElement Save()
        {
            return new XElement("priority",
                Xml.AddIf("id", ID),
                Xml.AddIf("name", Name),
                Xml.AddIf("icon", Icon));
        }

        public XElement SaveDirty()
        {
            return Save();
        }

        public bool Equals(Priority other)
        {
            if (ReferenceEquals(null, other))
                return false;
            if (ReferenceEquals(this, other))
                return true;
            return string.Equals(ID, other.ID) && string.Equals(Name, other.Name) && string.Equals(Icon, other.Icon);
        }

        public override string ToString()
        {
            return Name;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj))
                return false;
            if (ReferenceEquals(this, obj))
                return true;
            if (obj.GetType() != GetType())
                return false;
            return Equals((Priority) obj);
        }

        public override int GetHashCode()
        {
            unchecked
            {
                int hashCode = (ID != null ? ID.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ (Name != null ? Name.GetHashCode() : 0);
                hashCode = (hashCode * 397) ^ (Icon != null ? Icon.GetHashCode() : 0);
                return hashCode;
            }
        }

        public static bool operator ==(Priority left, Priority right)
        {
            return Equals(left, right);
        }

        public static bool operator !=(Priority left, Priority right)
        {
            return !Equals(left, right);
        }
    }
}